#ifndef G3_MESH_H
#define G3_MESH_H

#include "scenegraph.h"
#include "material.h"

#include <GL/gl.h>

#include <string>

namespace G3 {

using std::string;

class TRIANGLE_STRIPI {
	public:
		TRIANGLE_STRIPI ();
		~TRIANGLE_STRIPI ();

		uint num_indices;
		uint *indices;

//==============================================================================
// Allocates memory for a trianglestrip
//
//		uint NumIndices				The number of indices to allocate memory for
//==============================================================================
		void Create (uint numIndices);
};

class TRIANGLE_FANI {
	public:
		TRIANGLE_FANI ();
		~TRIANGLE_FANI ();

		uint num_indices;
		uint *indices;

//==============================================================================
// Allocates memory for a trianglefan
//
//		uint NumIndices				The number of indices to allocate memory for
//==============================================================================
		void Create (uint numIndices);
};

// TODO:: Colors and color indices aswell
class MESH_NODE: public G3::ANIM_NODE {
	public:
        MESH_NODE ();
		MESH_NODE (shared_ptr<OBJECT_NODE> nodeParent);
		~MESH_NODE ();

		uint num_tri_strips;
		TRIANGLE_STRIPI *tri_strips;

		uint num_tri_fans;
		TRIANGLE_FANI *tri_fans;

		uint num_verts;
		VEC3F *vertices;
		uint num_tex_coords;
		VEC2F *tex_coords;

		MATERIAL *material;

		string name;

//==============================================================================
// Creates a mesh and allocates memory for Vertices, TextureCoords, Strip, Fans
//
//		uint NumVerts				Number of vertices
//
//		uint NumTexCoords			Number of texture coordinates
//
//		uint NumStrips				Number of triangle strips
//
//		uint NumFans				Number of triangle fans
//==============================================================================
		bool Create (uint numVerts, uint numTexCoords = 0, uint numStrips = 0, uint numFans = 0);

//==============================================================================
// Sets the mesh material
//
//		MATERIAL *Material			Pointer to the material to use
//==============================================================================
		void SetMaterial (MATERIAL *aMaterial);

//==============================================================================
// Sets mesh vertices
//
//		VEC3F *Verts				Pointer to the array vertices
//
//	NOTE:: It copies NumVertices vertices from the array
//==============================================================================
		void SetVertices (VEC3F *verts);

//==============================================================================
// Sets mesh texture coordinates
//
//		VEC2F *TexCoords			Pointer to the array texture coordinates
//
//	NOTE:: It copies NumTextureCoords coordinates from the array
//		   The array should be ordered the same way the vertices are
//==============================================================================
		void SetTexCoords (VEC2F *texCoords);

//==============================================================================
// Sets mesh indices for a triangle strip
//
//		uint StripID				The index of the strip to set
//
//		uint NumIndices				Number of indices to set
//
//		uint Indices				Pointer to an array of indices
//
//	NOTE:: The same indices count for vertices and texture coordinates
//==============================================================================
		void SetStrip (uint stripID, uint numIndices, uint *aIndices);

//==============================================================================
// Sets mesh indices for a triangle fan
//
//		uint FanID					The index of the fan to set
//
//		uint NumIndices				Number of indices to set
//
//		uint Indices				Pointer to an array of indices
//
//	NOTE:: The same indices count for vertices and texture coordinates
//==============================================================================
		void SetFan (uint fanID, uint numIndices, uint *aIndices);

//==============================================================================
// Creates a cube with edge length Side
//==============================================================================
		void CreateCube (float side);

//==============================================================================
// Creates a plane with edge length Side
//==============================================================================
		void CreatePlane (float side);

//==============================================================================
// Multiplies WorldMatrix with ModelMatrix and applies it to OpenGL renderer
//==============================================================================
		void glApplyMatrix ();

//==============================================================================
// Renders the mesh with its children
//
//		float ElapsedTime			Time elapsed since the last call
//==============================================================================
		void Render (float elapsedTime);

//==============================================================================
// Updates the mesh with its children
//
//		float ElapsedTime			Time elapsed since the last call
//==============================================================================
		void Update (float elapsedTime);

//==============================================================================
// Clears the mesh
//==============================================================================
		void Clear ();
};

}

#endif
